Skip to content

fixes issue 17162 false positive for never type impls#17163

Open
durationextender wants to merge 1 commit into
rust-lang:masterfrom
durationextender:fix/unused-async-trait-impl-never-type
Open

fixes issue 17162 false positive for never type impls#17163
durationextender wants to merge 1 commit into
rust-lang:masterfrom
durationextender:fix/unused-async-trait-impl-never-type

Conversation

@durationextender

@durationextender durationextender commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Do not lint unused_async_trait_impl for impl Trait for ! blocks.

The never type ! can never be instantiated, so any method implemented
for it can never be called. Flagging these as having an "unused async"
is a false positive since the async keyword has no practical impact.

fixes #17162

changelog: [unused_async_trait_impl]: do not lint when the trait is implemented for the never type !

I ran the tests locally and pass, also did uibless and formatted the code

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Jun 5, 2026
@rustbot

rustbot commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

r? @Jarcho

rustbot has assigned @Jarcho.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: 8 candidates
  • 8 candidates expanded to 8 candidates
  • Random selection from Jarcho, dswij, llogiq, samueltardieu

@durationextender

Copy link
Copy Markdown
Contributor Author

@rustbot ready

@ada4a

ada4a commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

This should at least make sure that the trait method in question actually has self as a parameter -- associated functions can be called on ! just fine. For example, this code:

#![feature(never_type)]

trait Trait {
    fn foo() {
        eprintln!("default");
    }
}

impl Trait for ! {
    fn foo() {
        eprintln!("hi!!");
    }
}

fn main() {
    <! as Trait>::foo();
}

will successfully compile and print "hi!!".

This would be nice to add as a test case.

But before you do: I'm not actually sure this is the correct fix for the issue at hand, let me discuss that under the issue.

Comment on lines +260 to +265
&& let Some(builtin_crate) = clippy_utils::std_or_core(cx)
&& let Some(inner) = unpack_async_fn_body(cx, body)
// Find the tail expression contained in the async fn (if any),
// which will be wrapped in std::future::ready.
&& let ExprKind::Block(block, _) = inner.kind
&& let Some(tail_expr) = block.expr

@Jarcho Jarcho Jun 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These shouldn't be changed.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk why those got changed tbh maybe because of cargo dev fmt?

Comment on lines +267 to +274
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir_expect_item(parent);
let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip();
//check if self.ty is never type ! if it is, then we don't want to lint because the function can
// never be called and thus doesn't need to be async
if self_ty.is_never() {
return;
}

@Jarcho Jarcho Jun 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual important thing to check is if any of the input types are uninhabited. You can use Ty::is_inhabited_from.

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would mean that this check should be applied to freestanding functions as well, right? So it would probably make sense to extract it to a separate function, and call that both here and in check_fn

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay i will change the self_ty.is_never() to use is_inhabited_from instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you perhaps explain that func? the is_inhabited_from? because there is only 1 reference of it in the whole codebase and that ref is very vague of what is expects imo

@Jarcho Jarcho Jun 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything you need is in LateContext. You can get the DefId of the innermost enclosing item from cx.enclosing_body.unwrap().hir_id.owner.def_id.to_def_id() which can be used directly.

The function returns how the item passed views a type's inhabitedness. A struct containing a private uninhabited field can only be seen as uninhabited from items that can access that field.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Jun 6, 2026
@rustbot

rustbot commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot

rustbot commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

☔ The latest upstream changes (possibly #17181) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

unused_async_trait_impl is not working well with !

4 participants